// C++中的operator关键字及其多种用途
// operator关键字在C++中非常强大，不仅可以用于类型转换运算符，还有许多其他重要用途。让我详细介绍这些用法：

// 1. 运算符重载
// 最常见的用途是重载各种操作符，使自定义类型能够使用内置操作符语法。
// 二元运算符重载
class Complex
{
    double real, imag;

public:
    Complex(double r = 0, double i = 0) : real(r), imag(i) {}

    // 重载加法运算符
    Complex operator+(const Complex &other) const
    {
        return Complex(real + other.real, imag + other.imag);
    }

    // 重载乘法运算符
    Complex operator*(const Complex &other) const
    {
        return Complex(
            real * other.real - imag * other.imag,
            real * other.imag + imag * other.real);
    }
};

// 使用
Complex a(1, 2), b(3, 4);
Complex c = a + b; // 调用a.operator+(b)
Complex d = a * b; // 调用a.operator*(b)

// 一元运算符重载
class Integer
{
    int value;

public:
    Integer(int v = 0) : value(v) {}

    // 重载负号运算符
    Integer operator-() const
    {
        return Integer(-value);
    }

    // 重载前置递增运算符
    Integer &operator++()
    {
        ++value;
        return *this;
    }

    // 重载后置递增运算符（注意int参数）
    Integer operator++(int)
    {
        Integer temp = *this;
        ++value;
        return temp;
    }
};

// 使用
Integer i(5);
Integer j = -i;  // 调用i.operator-()
++i;             // 调用i.operator++()
Integer k = i++; // 调用i.operator++(0)

// 比较运算符重载
class String
{
    std::string data;

public:
    String(const char *s) : data(s) {}

    // 重载相等运算符
    bool operator==(const String &other) const
    {
        return data == other.data;
    }

    // 重载小于运算符
    bool operator<(const String &other) const
    {
        return data < other.data;
    }
};

// 使用
String s1("hello"), s2("world");
bool equal = (s1 == s2); // 调用s1.operator==(s2)
bool less = (s1 < s2);   // 调用s1.operator<(s2)

// 2. 下标运算符重载
// 允许使用数组下标语法访问自定义容器。
class Vector
{
    int *data;
    size_t size;

public:
    Vector(size_t s) : size(s), data(new int[s]) {}
    ~Vector() { delete[] data; }

    // 重载下标运算符（可读写版本）
    int &operator[](size_t index)
    {
        if (index >= size)
            throw std::out_of_range("Index out of bounds");
        return data[index];
    }

    // 重载下标运算符（只读版本）
    const int &operator[](size_t index) const
    {
        if (index >= size)
            throw std::out_of_range("Index out of bounds");
        return data[index];
    }
};

// 使用
Vector v(10);
v[0] = 42;        // 调用v.operator[](0)
int value = v[0]; // 调用v.operator[](0)

// 3. 函数调用运算符重载
// 允许对象像函数一样被调用，创建函数对象（仿函数）。
class Adder
{
    int base;

public:
    Adder(int b) : base(b) {}

    // 重载函数调用运算符
    int operator()(int value) const
    {
        return base + value;
    }
};

// 使用
Adder add5(5);
int result = add5(10); // 调用add5.operator()(10)，结果为15

// 4. 成员访问运算符重载
// 重载箭头运算符，通常用于智能指针实现
// unique_ptr和shared_ptr帮我们用模板与重载->实现了
template <typename T>
class SmartPtr
{
    T *ptr;

public:
    SmartPtr(T *p) : ptr(p) {}
    ~SmartPtr() { delete ptr; }

    // 重载箭头运算符
    T *operator->() const
    {
        return ptr;
    }

    // 重载解引用运算符
    T &operator*() const
    {
        return *ptr;
    }
};

// 使用
class Person
{
public:
    void sayHello() { std::cout << "Hello\n"; }
};

SmartPtr<Person> p(new Person());
p->sayHello();   // 调用p.operator->()->sayHello()
(*p).sayHello(); // 调用p.operator*().sayHello()

// 5. 类型转换运算符（之前讨论过）
// 允许自定义类型隐式或显式转换为其他类型。
class Fraction
{
    int num, den;

public:
    Fraction(int n, int d) : num(n), den(d) {}

    // 转换为double的运算符
    operator double() const
    {
        return static_cast<double>(num) / den;
    }

    // C++11引入的显式转换运算符
    explicit operator bool() const
    {
        return num != 0;
    }
};

// 使用
Fraction f(3, 4);
double d = f; // 调用f.operator double()
if (f)
{ /* ... */
} // 需要显式转换：if (static_cast<bool>(f))

// 6. 内存分配和释放运算符重载
// 自定义内存管理行为。
class MemoryTracker
{
    static size_t allocated;

public:
    // 重载new运算符
    void *operator new(size_t size)
    {
        allocated += size;
        return ::operator new(size);
    }

    // 重载delete运算符
    void operator delete(void *ptr, size_t size)
    {
        allocated -= size;
        ::operator delete(ptr);
    }

    static size_t getAllocated() { return allocated; }
};

size_t MemoryTracker::allocated = 0;

// 使用
MemoryTracker *obj = new MemoryTracker();
std::cout << "Allocated: " << MemoryTracker::getAllocated() << " bytes\n";
delete obj;
std::cout << "After delete: " << MemoryTracker::getAllocated() << " bytes\n";

// 7. 全局运算符重载
// 在类外部定义运算符重载，通常用于对称操作或I/O操作
class Point
{
public:
    int x, y;
    Point(int _x = 0, int _y = 0) : x(_x), y(_y) {}
};

// 全局运算符重载
Point operator+(const Point &lhs, const Point &rhs)
{
    return Point(lhs.x + rhs.x, lhs.y + rhs.y);
}

// 流插入运算符重载
std::ostream &operator<<(std::ostream &os, const Point &p)
{
    return os << "(" << p.x << ", " << p.y << ")";
}

// 使用
Point p1(1, 2), p2(3, 4);
Point p3 = p1 + p2; // 调用operator+(p1, p2)
std::cout << p3;    // 调用operator<<(std::cout, p3)

// 8. 字面量运算符重载（C++11）
// 允许自定义字面量后缀。
// 自定义字面量：5_km 表示5公里（单位：米）
constexpr long double operator"" _km(long double km)
{
    return km * 1000.0;
}

// 自定义字面量：5_MB 表示5兆字节（单位：字节）
constexpr size_t operator"" _MB(unsigned long long mb)
{
    return mb * 1024 * 1024;
}

// 使用
auto distance = 5.5_km; // 5500.0米
auto fileSize = 10_MB;  // 10485760字节

// 总结
// operator关键字在C++ 中非常强大，它允许：

// 重载算术、比较、逻辑等基本运算符
// 实现下标访问、函数调用和成员访问
// 定义类型转换规则
// 自定义内存管理
// 创建全局运算符函数
// 定义自定义字面量 通过合理使用运算符重载，可以使自定义类型的使用更加自然、直观，提高代码的可读性和表达能力。但也需要注意不要滥用，保持语义的一致性和直观性。